package com.zx.servicelearn.service;

import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import com.zx.servicelearn.aidl.IBookManager;
import com.zx.servicelearn.aidl.IOnNewBookArrivedListener;
import com.zx.servicelearn.model.Book;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

public class IPCService2_AIDL extends Service {
    private AtomicBoolean mIsServiceDestoryed = new AtomicBoolean(false);//原子性的boolean
    private CopyOnWriteArrayList<Book> list = new CopyOnWriteArrayList<>();//支持并发读写的list
    private RemoteCallbackList<IOnNewBookArrivedListener> mListenerList = new RemoteCallbackList<>();//RemoteCallbackList 用于AIDL中注册和注销接口


    Binder mBinder = new IBookManager.Stub() {
        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            // TODO: 2018/1/19 权限验证 2 onTransact中验证 这边验证可以保证客户端能连上服务端，但是不能调用服务端方法，每次调用方法都会执行该方法

            //permission验证
            int check = checkCallingOrSelfPermission("com.zx.servicelearn.permission.ACCESS_BOOK_SERVICE");
            if (check == PackageManager.PERMISSION_DENIED) {
                Log.e("IPCService2_AIDL", "onTransact,fail:no permission");
                return false;
            }
            Log.e("IPCService2_AIDL", "onTransact,success:has permission");

            //Uid Pid验证 验证包名
            String packageName = null;
            String[] packages = getPackageManager().getPackagesForUid(getCallingUid());
            if (packages != null && packages.length > 0) {
                packageName = packages[0];
            }
            if (packageName == null) {
                Log.e("IPCService2_AIDL", "onTransact,fail:packageName is null");
                return false;
            }
            if (!packageName.startsWith("com.zx.servicelearn")) {//包名为com.zx.servicelearn的客户端才能调用此服务端接口
                Log.e("IPCService2_AIDL", "onTransact,fail:packageName is error");
                return false;
            }
            Log.e("IPCService2_AIDL", "onTransact,success:packageName is right");
            return super.onTransact(code, data, reply, flags);
        }

        @Override
        public List<Book> getBookList() throws RemoteException {
            // TODO: 2018/1/19 模拟耗时操作 主线程注意耗时操作会导致ANR 所以尽量使用子线程处理耗时操作，如果需要返回值，可以使用接口监听来处理
//            try {
//                Thread.sleep(10000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            return list;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            list.add(book);
        }

        @Override
        public void registerListener(IOnNewBookArrivedListener listener) throws RemoteException {
//            if (!mListenerList.contains(listener)) {
//                mListenerList.add(listener);
//            } else {
//                Log.e("IPCService2_AIDL", "already exists.");
//            }
            mListenerList.register(listener);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                Log.e("IPCService2_AIDL", "registerListener,size:" + mListenerList.getRegisteredCallbackCount());
            }
        }

        @Override
        public void unregisterListener(IOnNewBookArrivedListener listener) throws RemoteException {
//            if (!mListenerList.contains(listener)) {
//                mListenerList.remove(listener);
//                Log.e("IPCService2_AIDL", "unregister listener success.");
//            } else {
//                Log.e("IPCService2_AIDL", "already exists.");
//            }
//            Log.e("IPCService2_AIDL", "registerListener,size:" + mListenerList.size());
            mListenerList.unregister(listener);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                Log.e("IPCService2_AIDL", "registerListener,size:" + mListenerList.getRegisteredCallbackCount());
            }
        }
    };


    public IPCService2_AIDL() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        new Thread(new ServiceWorker()).start();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: 2018/1/19 权限验证 1 onBind中验证 这边验证会使得客户端连接服务端失败！导致客户端的Binder为空
        int check = checkCallingOrSelfPermission("com.zx.servicelearn.permission.ACCESS_BOOK_SERVICE");
        if (check == PackageManager.PERMISSION_DENIED) {
            Log.e("IPCService2_AIDL", "onBind,fail:no permission");
            return null;
        }
        Log.e("IPCService2_AIDL", "onBind,success:has permission");

        return mBinder;
    }

    @Override
    public void onDestroy() {
        mIsServiceDestoryed.set(true);
        super.onDestroy();
    }


    private class ServiceWorker implements Runnable {

        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see Thread#run()
         */
        @Override
        public void run() {
            while (!mIsServiceDestoryed.get()) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                int bookId = list.size() + 1;

                Book newBook = new Book(bookId, "#new book#" + bookId);
                try {
                    onNewBookArrived(newBook);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void onNewBookArrived(Book book) throws RemoteException {
        list.add(book);
//        for (int i = 0; i < mListenerList.size(); i++) {
//            IOnNewBookArrivedListener mIOnNewBookArrivedListener = mListenerList.get(i);
//            Log.e("IPCService2_AIDL", "notify listeners::" + mIOnNewBookArrivedListener);
//            mIOnNewBookArrivedListener.onNewBookArrived(book);
//
//        }
        final int N = mListenerList.beginBroadcast();
        Log.e("IPCService2_AIDL", "notify listeners:,listener list size:" + N);
        Log.e("IPCService2_AIDL", "notify listeners:,book list size:" + list.size());
        for (int i = 0; i < N; i++) {
            IOnNewBookArrivedListener mIOnNewBookArrivedListener = mListenerList.getBroadcastItem(i);
            if (mIOnNewBookArrivedListener != null) {
                mIOnNewBookArrivedListener.onNewBookArrived(book);
            }
        }
        mListenerList.finishBroadcast();
    }


}
